﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using ModelCreator.Model;
using ZzFw.FormUI;
using ZzFw.CommonLib.Util;
using System.Text.RegularExpressions;
using Newtonsoft.Json;

namespace ModelCreator
{
    public partial class FrmMain : Form
    {
        PropList propList;
        string setfilePath;

        const string DEF_CS_PATH = "cs\\";
        const string DEF_ORACLE_PATH = "oracle\\";

        public FrmMain()
        {
            InitializeComponent();
            dgv.AutoGenerateColumns = false;
            propList = new PropList();
            setfilePath = Path.Combine(Application.StartupPath, "temp\\");
            MsgUtil.Title = this.Text;
        }

        #region 文件操作
        private string GetFileFullname(string filename)
        {
            return Path.Combine(setfilePath, filename);
        }

        private string GetCSharpModelFilename(string path, string modelName)
        {
            return Path.Combine(path, DEF_CS_PATH + modelName + ".cs");
        }

        private string GetOracleSqlFilename(string path, string modelName)
        {
            return Path.Combine(path, DEF_ORACLE_PATH + modelName + ".sql");
        }

        private string GetSetFilename(string path, string modelName)
        {
            return Path.Combine(path, modelName + ".mdl");
        }


        
        #endregion

        #region 类属性操作
        void AddProp()
        {
            if (!PropInputValid())
            {
                return;
            }

            if (PropIndexByName(txtPropName.Text.Trim()) > -1)
            {
                MessageBox.Show("属性名称不能重复！", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }

            dgv.DataSource = null;

            Prop p = new Prop();
            p.PropName = txtPropName.Text.Trim();
            p.PropType = txtType.Text.Trim();
            p.PropDesc = txtDesc.Text.Trim();
            p.DbFieldType = OracleUtil.ParseType(p.PropType);
            propList.Add(p);

            dgv.DataSource = propList;

            txtPropName.Clear();
            txtDesc.Clear();
            txtPropName.Focus();
        }

        void DelProp()
        {
            if (dgv.SelectedCells.Count == 0)
            {
                return;
            }

            string pname = dgv.Rows[dgv.SelectedCells[0].RowIndex].Cells[1].Value.ToString();

            int idx = PropIndexByName(pname);
            if (idx > -1)
            {
                dgv.DataSource = null;
                propList.RemoveAt(idx);
                dgv.DataSource = propList;
            }
        }

        bool PropInputValid()
        {
            return txtPropName.Text.Trim().Length > 0 && txtType.Text.Trim().Length > 0;
        }

        int PropIndexByName(string pname)
        {
            return propList.FindIndex(delegate(Prop p)
            {
                if (p.PropName == pname)
                {
                    return true;
                }
                return false;
            });
        }
        #endregion

        #region 类配置
        private void SaveSetFile(string file, PropList list)
        {
            //SerializeUtil.ToXmlFile(list, file);            
            string json = JsonConvert.SerializeObject(list);
            StringWriter sw = new StringWriter();
            JsonTextWriter jtw = new JsonTextWriter(sw);
            jtw.WriteStartObject();

            jtw.WritePropertyName("ModelName");
            jtw.WriteValue(list.ModelName);

            jtw.WritePropertyName("TablePreName");
            jtw.WriteValue(list.TablePreName);

            jtw.WritePropertyName("Items");
            jtw.WriteRawValue(json);

            jtw.WriteEndObject();
            
            FileUtil.WriteText(file, sw.ToString());
            jtw.Close();
        }

        private PropList LoadSetFile(string file)
        {            
            string json = FileUtil.ReadText(file);
            Dictionary<string, object> oo = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
            List<Prop> tmp = JsonConvert.DeserializeObject<List<Prop>>(oo["Items"].ToString());
            PropList list = new PropList();
            list.ModelName = oo["ModelName"].ToString();
            list.TablePreName = oo["TablePreName"].ToString();
            list.AddRange(tmp);
            return list;
            
        }

        private string[] GetSetFiles(string path)
        {
            return FileUtil.GetFiles(path, @"\.mdl", true);
        }

        private void ImportFromCS(string[] csFiles)
        {
            foreach (string file in csFiles)
            {
                TransCs2Setfile(file, setfilePath);
            }

            if (lstModelSet.Items.Count > 0 && lstModelSet.SelectedIndex == -1)
            {
                lstModelSet.SelectedIndex = 0;
            }
        }

        private bool TransCs2Setfile(string csFile, string mdlPath)
        {
            string content = File.ReadAllText(csFile);
            Regex reModelName = new Regex("class\\s+(\\w+)");
            Regex reProps = new Regex("public\\s+(\\w+)\\s+(\\w+)\\s*\\n");

            PropList list = new PropList();

            Match m1 = reModelName.Match(content);
            if (m1.Success)
            {
                list.ModelName = m1.Groups[1].Value;
            }

            MatchCollection mc = reProps.Matches(content);
            foreach (Match m in mc)
            {
                string t = m.Groups[1].Value;
                if (t != "class")
                {
                    Prop p = new Prop();
                    p.PropType = t;
                    p.PropName = m.Groups[2].Value;
                    p.DbFieldType = OracleUtil.ParseType(p.PropType);
                    list.Add(p);
                }
            }

            SaveSetFile(GetSetFilename(mdlPath, list.ModelName), list);

            return true;
        }
        #endregion
       
        #region C#模型类

        private bool CreateCSharpModel(string file, PropList list)
        {
            string s = ModelUtil.CreateModel(list);
            return FileUtil.WriteText(file, s);
        }

        private void CopyCSharpModel()
        {            
            //propList.ModelName = txtModelName.Text.Trim(); 
            string s = ModelUtil.CreateModel(propList);
            Clipboard.SetText(s);
            MsgUtil.Info("已复制到剪贴板");
        }

        #endregion

        #region Oracle建表

        #endregion

        #region UI

        void RefreshSetfileList(string path)
        {
            if (string.IsNullOrEmpty(path)) { return; }

            FileUtil.CheckFilePath(path, true);
            setfilePath = path;
            
            string[] files = this.GetSetFiles(path);
            FillSetfileList(files);
        }

        void FillSetfileList(string[] files)
        {
            lstModelSet.Items.Clear();
            foreach (string file in files)
            {
                ListItem item = new ListItem(Path.GetFileName(file), file);
                lstModelSet.Items.Add(item);
            }
        }

        void ShowPropList(PropList list)
        {
            dgv.DataSource = null;            
            dgv.DataSource = list;            
            txtModelName.Text = list.ModelName;
        }

        #endregion

        #region 事件

        #region 窗体
        private void FrmMain_Load(object sender, EventArgs e)
        {
            txtPath.Text = setfilePath;
            RefreshSetfileList(setfilePath);
        }

        private void FrmMain_Shown(object sender, EventArgs e)
        {
            txtType.Focus();
        }

        #endregion

        #region 菜单
        private void mnuExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void mnuImportFromCS_Click(object sender, EventArgs e)
        {
            if (dlgOpenFile.ShowDialog() == DialogResult.OK)
            {
                ImportFromCS(dlgOpenFile.FileNames);
                RefreshSetfileList(setfilePath);
            }
        }

        private void mnuSaveSetfile_Click(object sender, EventArgs e)
        {
            string file =GetSetFilename(setfilePath,propList.ModelName);
            SaveSetFile(file, propList);
        }
        #endregion

        #region 左侧栏
        private void btnBrowse_Click(object sender, EventArgs e)
        {
            if (dlgFolder.ShowDialog() == DialogResult.OK)
            {
                txtPath.Text = setfilePath;
                RefreshSetfileList(dlgFolder.SelectedPath);                
            }
        }

        private void txtPath_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Enter)
            {
                RefreshSetfileList(txtPath.Text.Trim());
            }
        }

        private void lstModelSet_SelectedIndexChanged(object sender, EventArgs e)
        {
            int idx = lstModelSet.SelectedIndex;
            if (idx == -1) { return; }

            string file = (lstModelSet.SelectedItem as ListItem).Value;
            propList = LoadSetFile(file);
            ShowPropList(propList);
        }
        #endregion

        #region 右侧栏
        private void btnCopy_Click(object sender, EventArgs e)
        {
            CopyCSharpModel();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            AddProp();
        }

        private void btnDel_Click(object sender, EventArgs e)
        {
            DelProp();
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            dgv.DataSource = null;
            propList = new PropList();
            dgv.DataSource = propList;
        }

        private void prop_KeyPress(object sender, KeyPressEventArgs e)
        {
            if ((int)e.KeyChar == (int)Keys.Enter && PropInputValid())
            {
                AddProp();
            }
        }

        private void prop_Enter(object sender, EventArgs e)
        {
            TextBox c = (TextBox)sender;
            c.SelectAll();
        }

        private void dgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            for (int i = 0; i < dgv.Rows.Count; i++)
            {
                dgv.Rows[i].Cells[0].Value = (i + 1).ToString();
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            string file = GetSetFilename(setfilePath, propList.ModelName);
            SaveSetFile(file, propList);
            RefreshSetfileList(setfilePath);
        }
        #endregion

        private void txtModelName_Leave(object sender, EventArgs e)
        {
            if (txtModelName.Text.Trim().Length > 0)
            {
                propList.ModelName = txtModelName.Text.Trim();
            }
        }
        #endregion
    }
}